shared/logs/ 아래, 인스턴스마다 한 파일 — application-10001.log 와 application-10000.log. 릴리스마다 링크로 들어가므로 배포해도 이어진다(Dev Deploying). 두 인스턴스의 시간순을 한 줄로 보려면 둘을 sort -m 하면 된다.
날마다 application-<port>.<날짜>.log.gz 로 말아 30일, 합쳐서 1GB 까지만 둔다. 설정은 conf/logback.xml 이고 서버에는 아무것도 없다 — Play 가 릴리스의 conf/ 를 읽는다.
2026-09-26 전에는 한 파일에 둘이 같이 썼고 아무것도 안 잘랐다. 8-03 부터 53일치가 491MB 로 쌓였고 디스크는 74% 였다. /hc 는 여유가 5% 아래면 실패하니(Dev Deploying 의 헬스체크) 그대로면 언젠가 배포가 디스크에서 멈췄을 것이다. 파일을 인스턴스마다 나눈 것은 취향이 아니다 — 프로세스 둘이 한 파일을 자정에 서로 이름 바꾸려 들면 한쪽이 진다. 옛 application.log 는 그대로 남아 있고, 필요 없어지면 손으로 지운다.
문제를 찾는 데 쓴 것은 이 한 줄이다. 500 응답마다 Unexpected exception[...] 줄이 남으므로, 그것을 종류별로 세면 «지금 무엇이 깨져 있나» 가 그대로 나온다.
sudo grep -h 'Unexpected exception\[' application-*.log \ sed -E 's/.*Unexpected exception\[//; s/\].*//; s/[0-9]+/<n>/g' \ sort | uniq -c | sort -rn | head -20
날짜별로 보려면 직전 날짜 줄을 기억하며 세면 된다. 예외 줄 자체에는 시각이 없다.
sudo awk '/^[0-9]{4}-[0-9]{2}-[0-9]{2} /{d=substr($0,1,10)} /Unexpected exception\[/{e=$0; sub(/.*Unexpected exception\[/,"",e); sub(/:.*/,"",e); print d, e}' application-10001.log \ sort | uniq -c
어느 코드에서 났는지는 예외 줄 다음의 스택에서 첫 애플리케이션 프레임만 보면 된다.
sudo awk '/Unexpected exception\[NoSuchElementException/{f=1;next} f&&/^[[:space:]]*at (controllers|logics|models|actors)\./{print $0; f=0}' application-*.log \ sort | uniq -c | sort -rn
53일치에 [ERROR] 8,403 줄, [WARN] 262,607 줄. 500 을 종류별로 세니 이렇게 나왔다.
건수 | 예외 | 무엇이었나 |
|---|---|---|
7,103 |
| 9-03·9-04 에 몰려 있다(하루 5,804). 9-16 이후로는 없다. 그날 무슨 일이 있었는지는 Dev BotDetection 과 Dev Deploying 의 9-04 항목 |
727 |
| 726 이 |
131 |
| JDK 가 돌고 있는 JVM 아래에서 갈렸을 때. Dev Deploying 의 그 절 |
62 |
| 전부 9-25, 빈 |
35 |
|
|
20 |
| 빈 |
13 |
| 전부 8-03 하루. 지금 버전은 멀쩡하다 |
10+3+2 |
| 괄호 없는 매크로와 없는 날짜(Macro, MacroWeekdayName) |
고친 것(2026-09-25). 폼이 아닌 본문은 이제 400 이다 — FormResults 를 쓰는 일곱 엔드포인트 전부. 읽을 수 있는 페이지가 없을 때의 Random 은 FrontPage 로 보낸다. 나머지는 위 표의 링크에 있다.
cookie has invalid signature 63,953 — 8-23~8-27 에 몰려 있다(하루 1,400 대). 그 뒤로는 거의 없다. 서명 키가 바뀌면 그때까지의 세션 쿠키가 전부 이렇게 되므로(AccessControl 의 signed read URL 절에 같은 이야기가 있다), 그 무렵에 키를 바꾼 것으로 보인다. 추측이니 확인이 필요하다.WebSocket watch denied 76,000 — 8월에 몰려 있고 주소 셋이 대부분이다(한 주소가 44,249). 읽기 권한이 없는 페이지의 소켓은 거절되는데, 브라우저 쪽은 닫히면 다시 연결하므로(Dev WebSocket 의 재연결) 탭 하나가 며칠을 두드릴 수 있다. 2026-09-26 부터 거절된 핸드셰이크는 다섯 번에서 그만둔다(Dev WebSocket 의 연결/재연결).HTTP idle-timeout 하루 60~90 건은 정상 범위로 본다 — 탭이 잠들면 나는 것이다.페이지 계산은 비동기라, 계산하는 사이에 그 리비전이 사라지면 부모 행이 없어 실패한다.
PageMeta.upsert 의 외래키 위반 20건 — 아직 난다(9-09에 11, 9-13에 6, 9-16·9-22에 하나씩). PageLogic.calculate 가 최신 리비전을 읽고 PageMeta 를 쓰는 사이에, 다른 요청이 그 리비전을 지우거나 페이지 이름을 바꾸면 난다. 계산은 거기서 멈추므로 그 페이지의 링크·단어 통계가 낡은 채로 남지만, 지우는 쪽도 rename 하는 쪽도 제 Calculate 를 넣고 한 시간마다 도는 보수 작업도 있어 저절로 낫는다. 그래서 고치지 않고 적어 둔다 — 고친다면 «리비전이 사라졌으면 조용히 그만둔다» 이고, 그 판단은 소유자 몫이다.CalculatedTermFrequency·CalculatedTerm 의 중복 키 51건은 8월에 멈췄다. 두 곳 다 REPLACE · ON DUPLICATE KEY UPDATE 로 고쳤고 그 이유가 코드 옆에 적혀 있다.IpDeny·RateLimit 로 403 을 받은 요청이 9-19 하루 1,147건에서 9-25 하루 5,373건으로 늘었다. 막힌 주소는 하루 60~200개이고, 많이 막힌 쪽은 전부 데이터센터 주소(34.·35.·185. 대)다 — 사람이 아니라 크롤러가 늘어난 것이고, Dev BotDetection 이 설계대로 막고 있는 것이다. 사람이 걸렸다는 신호는 아직 없다.
Similar pages by cosine similarity. Words after page name are term frequency.